package Project;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Group;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.axis.SymbolAxis;
import org.jfree.chart.labels.CategoryItemLabelGenerator;
import org.jfree.chart.labels.IntervalCategoryItemLabelGenerator;
import org.jfree.chart.labels.IntervalXYItemLabelGenerator;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.XYItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.renderer.category.GanttRenderer;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.IntervalCategoryDataset;
import org.jfree.data.gantt.Task;
import org.jfree.data.gantt.TaskSeries;
import org.jfree.data.gantt.TaskSeriesCollection;
import org.jfree.data.gantt.XYTaskDataset;
import org.jfree.data.time.Day;
import org.jfree.data.time.Hour;
import org.jfree.data.time.SimpleTimePeriod;
import org.jfree.data.time.TimePeriod;
import org.jfree.data.xy.IntervalXYDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.TextAnchor;
import static javax.swing.GroupLayout.Alignment.*;
import static javax.swing.GroupLayout.Alignment.*;


public class MyopicGUI extends JFrame implements ActionListener {
	private JTextArea textArea;
	private JPanel taskPanel;
	private JPanel graphPanel;
	private Myopic m;

	public MyopicGUI()
	{
		setTitle("Multiprocessor Scheduler");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//setPreferredSize(800, 600);
		setMinimumSize(new Dimension(800, 700));
		setResizable(false);
		getContentPane().setLayout(new BorderLayout());
		setupGUI();
		pack();
		setVisible(true);

	}
	private void test()
	{
		graphPanel = createDemoPanel();
		getContentPane().add(graphPanel, BorderLayout.CENTER);
	}


	private JPanel createRowOfTextBoxes()
	{
		JPanel panel = new JPanel();

		JLabel label = new JLabel("Task:");

		int num = taskPanel.getComponentCount() -1;
		JLabel taskID = new JLabel("T"+num);
		taskID .setPreferredSize(new Dimension(100,20));

		JTextField textField2 = new JTextField();
		textField2.setPreferredSize(new Dimension(100,20));

		JTextField textField3 = new JTextField();
		textField3.setPreferredSize(new Dimension(100,20));

		JTextField textField4 = new JTextField();
		textField4.setPreferredSize(new Dimension(100,20));

		String[] options = { "No", "Exclusive", "Shared" };

		JComboBox resource1 = new JComboBox(options);
		resource1.setPreferredSize(new Dimension(100,20));
		JComboBox resource2 = new JComboBox(options);
		resource2.setPreferredSize(new Dimension(100,20));

		panel.add(label);
		panel.add(taskID );
		panel.add(textField2);
		panel.add(textField3);
		panel.add(textField4);


		panel.add(resource1);
		panel.add(resource2);
		return panel;
	}
	//public Myopic( int processors, int backtracks, int kValue, int WValue, ArrayList<SingleTask> tasks, JTextArea area)

	//	public SingleTask( int TaskId, int ReadyTime, int CompTime, int Deadline, Resource r, Resource r2 )

	private JPanel createRowOfLabels()
	{
		JPanel panel = new JPanel();

		JLabel blankLabel = new JLabel();
		blankLabel.setPreferredSize(new Dimension(30,20));

		JLabel label = new JLabel("Task ID");
		label.setPreferredSize(new Dimension(100,20));

		JLabel label2 = new JLabel("Ready Time");
		label2.setPreferredSize(new Dimension(100,20));

		JLabel label3 = new JLabel("Comp Time");
		label3.setPreferredSize(new Dimension(100,20));

		JLabel label4 = new JLabel("Deadline");
		label4.setPreferredSize(new Dimension(100,20));

		JLabel label5 = new JLabel("Resource One");
		label5.setPreferredSize(new Dimension(100,20));

		JLabel label6 = new JLabel("Resource Two");
		label6.setPreferredSize(new Dimension(100,20));


		panel.add(blankLabel);
		panel.add(label);
		panel.add(label2);
		panel.add(label3);
		panel.add(label4);
		panel.add(label5);
		panel.add(label6);

		return panel;
	}
	private JPanel createButtons()
	{
		JPanel panel = new JPanel();

		JLabel backtracks = new JLabel("Max Backtracks:");

		JTextField backtracksTextField = new JTextField("0");
		backtracksTextField.setPreferredSize(new Dimension(50,20));

		JLabel kval = new JLabel("K value:");

		JTextField kvalTextField = new JTextField("0");
		kvalTextField.setPreferredSize(new Dimension(50,20));

		JLabel wval = new JLabel("W value:");

		JTextField wvalTextField = new JTextField("0");
		wvalTextField.setPreferredSize(new Dimension(50,20));

		JButton addTask = new JButton("Add Task");
		addTask.addActionListener(this);
		addTask.setActionCommand("Add Task");

		JButton reset = new JButton("Reset");
		reset.addActionListener(this);
		reset.setActionCommand("Reset");

		JButton schedule = new JButton("Schedule");
		schedule.addActionListener(this);
		schedule.setActionCommand("Schedule");

		panel.add(backtracks);
		panel.add(backtracksTextField);
		panel.add(kval);
		panel.add(kvalTextField);
		panel.add(wval);
		panel.add(wvalTextField);
		panel.add(addTask);
		panel.add(reset);
		panel.add(schedule);
		return panel;
	}
	private void setupTextBoxes()
	{
		taskPanel = new JPanel();
		taskPanel.add(createButtons());
		taskPanel.add(createRowOfLabels());
		taskPanel.add(createRowOfTextBoxes());
		getContentPane().add(taskPanel, BorderLayout.CENTER);

	}
	private void setupGUI()
	{
		JPanel panel = new JPanel();
		//getContentPane().add(panel, BorderLayout.CENTER);
		panel.setLayout(new BorderLayout());

		textArea = new JTextArea();
		textArea.setEditable(false);
		textArea.setBackground(Color.WHITE);
		textArea.setBorder(BorderFactory.createLineBorder(Color.black));

		JScrollPane scrollPane = new JScrollPane(textArea);
		scrollPane.setPreferredSize(new Dimension(800, 250));

		panel.add(scrollPane, BorderLayout.CENTER);

		JMenuBar menubar = new JMenuBar();	
		JMenu menu = new JMenu("File");
		JMenuItem reset = new JMenuItem("Reset");
		reset.addActionListener(this);
		reset.setActionCommand("ResetMenu");

		menu.add(reset);
		menubar.add(menu);

		getContentPane().add(menubar, BorderLayout.NORTH);
		getContentPane().add(panel, BorderLayout.SOUTH);
	}

	private void testMyopicCreation()
	{
		ArrayList<SingleTask> tasks = new ArrayList<SingleTask>();
		tasks.add(new SingleTask(1,0,6,10, Resource.NO, Resource.NO));
		tasks.add(new SingleTask(2,2,7,13, Resource.SHARE, Resource.NO));
		tasks.add(new SingleTask(3,1,3,16, Resource.EXCLUSIVE, Resource.NO));
		tasks.add(new SingleTask(4,2,7,17, Resource.NO, Resource.NO));
		tasks.add(new SingleTask(5,3,9,19, Resource.NO, Resource.NO));

		ArrayList<SingleTask> tasks2 = new ArrayList<SingleTask>();
		tasks2.add(new SingleTask(1,0,28,80, Resource.SHARE, Resource.NO));
		tasks2.add(new SingleTask(2,0,24,73, Resource.NO, Resource.EXCLUSIVE));
		tasks2.add(new SingleTask(3,14,39,95, Resource.EXCLUSIVE, Resource.EXCLUSIVE));
		tasks2.add(new SingleTask(4,5,25,89, Resource.SHARE, Resource.NO));
		tasks2.add(new SingleTask(5,35,21,108, Resource.NO, Resource.SHARE));

		m = new Myopic(2, 3, 3,0, tasks, textArea);
		
		if(!m.ExecuteMyopic())
		{
			JOptionPane.showMessageDialog(this, "Max backtracks exceeded.");
		}
		

	}
	private  JFreeChart createChart(IntervalXYDataset paramIntervalXYDataset)
	{
		JFreeChart localJFreeChart = ChartFactory.createXYBarChart("Schedule", "Processor", false, "Timing", paramIntervalXYDataset, PlotOrientation.HORIZONTAL, true, false, false);
		localJFreeChart.setBackgroundPaint(Color.white);
		XYPlot localXYPlot = (XYPlot)localJFreeChart.getPlot();
		SymbolAxis localSymbolAxis = new SymbolAxis("Schedule", new String[] { "Processor Two", "Processor One" });
		localSymbolAxis.setGridBandsVisible(false);
		localXYPlot.setDomainAxis(localSymbolAxis);
		XYBarRenderer localXYBarRenderer = (XYBarRenderer)localXYPlot.getRenderer();
		localXYBarRenderer.setUseYInterval(true);
		localXYPlot.setRangeAxis(new NumberAxis("Timing"));

		NumberAxis range = (NumberAxis) localXYPlot.getRangeAxis();
		range.setRange(0, (m.getMaximumReady() + 2));
		range.setTickUnit(new NumberTickUnit(5));
		ChartUtilities.applyCurrentTheme(localJFreeChart);

		XYBarRenderer r = (XYBarRenderer) localXYPlot.getRenderer();
		r.setDrawBarOutline(true);


		XYPlot plot = (XYPlot) localJFreeChart.getPlot();
		XYItemRenderer renderer = plot.getRenderer();

		//PROCESSOR ONE
		renderer.setSeriesItemLabelGenerator(1, new IntervalXYItemLabelGenerator(){
			public String generateLabel(XYDataset dataset, int series, int item){
				if(dataset.getClass() == XYTaskDataset.class )
				{
					XYTaskDataset set = (XYTaskDataset) dataset;
					return (set.getTasks().getSeries(series).get(item).getDescription() + ": " + super.generateLabel(dataset, series, item));
				}
				else
					return super.generateLabel(dataset, series, item);
			}
		});

		//PROCESSOR TWO
		renderer.setSeriesItemLabelGenerator(0, new IntervalXYItemLabelGenerator(){
			public String generateLabel(XYDataset dataset, int series, int item){
				if(dataset.getClass() == XYTaskDataset.class )
				{
					XYTaskDataset set = (XYTaskDataset) dataset;
					return (set.getTasks().getSeries(series).get(item).getDescription() + ": " + super.generateLabel(dataset, series, item));
				}
				else
					return super.generateLabel(dataset, series, item);
			}
		});
		renderer.setBaseItemLabelsVisible(true);
		renderer.setBaseItemLabelPaint(Color.BLACK);
		renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition( ItemLabelAnchor.INSIDE6, TextAnchor.BOTTOM_CENTER));

		return localJFreeChart;
	}

	public  JPanel createDemoPanel()
	{
		return new ChartPanel(createChart(createDataset()));
	}
	private IntervalXYDataset createDataset()
	{
		return new XYTaskDataset(createTasks());
	}

	private TaskSeriesCollection createTasks()
	{
		TaskSeriesCollection localTaskSeriesCollection = new TaskSeriesCollection();

		TaskSeries localTaskSeries2 = new TaskSeries("Processor One");
		m.populateProcessorOneTaskSeries(localTaskSeries2);

		TaskSeries localTaskSeries1 = new TaskSeries("Processor Two");
		m.populateProcessorTwoTaskSeries(localTaskSeries1);

		localTaskSeriesCollection.add(localTaskSeries1);
		localTaskSeriesCollection.add(localTaskSeries2);

		return localTaskSeriesCollection;
	}

	public static void main(String[] args)
	{
		MyopicGUI m = new MyopicGUI();
		m.setupTextBoxes();
		m.revalidate();
	}
	@Override
	public void actionPerformed(ActionEvent e)
	{
		if(e.getActionCommand() == "Add Task")
		{
			taskPanel.add(createRowOfTextBoxes());
			taskPanel.revalidate();
		}
		else if(e.getActionCommand() == "Reset")
		{
			getContentPane().remove(taskPanel);
			taskPanel = new JPanel();

			taskPanel.add(createButtons());
			taskPanel.add(createRowOfLabels());
			taskPanel.add(createRowOfTextBoxes());
			getContentPane().add(taskPanel, BorderLayout.CENTER);
			revalidate();
		}
		else if(e.getActionCommand() == "Schedule")
		{
			ArrayList<SingleTask> tasks = new ArrayList<SingleTask>();
			JPanel panel1 = (JPanel) taskPanel.getComponent(0);
			int backtracks = Integer.parseInt( ((JTextField)panel1.getComponent(1)).getText());
			int kval = Integer.parseInt( ((JTextField)panel1.getComponent(3)).getText());
			int wval = Integer.parseInt( ((JTextField)panel1.getComponent(5)).getText());


			
			for(int i = 2; i< taskPanel.getComponentCount(); i++)
			{
				JPanel panel = (JPanel) taskPanel.getComponent(i);
				JTextField readytime = (JTextField) panel.getComponent(2);
				JTextField comptime = (JTextField) panel.getComponent(3);
				JTextField deadlinej = (JTextField) panel.getComponent(4);
				JComboBox r1 = (JComboBox) panel.getComponent(5);
				JComboBox r2 = (JComboBox) panel.getComponent(6);
				Resource resource1 = Resource.NO;
				Resource resource2 = Resource.NO;

				if(r1.getSelectedIndex() == 1)
				{
					resource1 = Resource.EXCLUSIVE;
				}
				else if(r1.getSelectedIndex() == 2)
				{
					resource1 = Resource.SHARE;
				}

				if(r2.getSelectedIndex() == 1)
				{
					resource2 = Resource.EXCLUSIVE;
				}
				else if(r2.getSelectedIndex() == 2)
				{
					resource2 = Resource.SHARE;
				}
				try{
					int readyTime = Integer.parseInt( readytime.getText());
					int compTime = Integer.parseInt( comptime.getText());
					int deadline = Integer.parseInt( deadlinej.getText());
					tasks.add( new SingleTask(i-1,readyTime,compTime,deadline, resource1, resource2));
				}
				catch(NumberFormatException e1){
					JOptionPane.showMessageDialog(this, "Please enter valid input.");
					return;
				}
			}

			getContentPane().remove(taskPanel);
			

			m = new Myopic(2, backtracks, kval, wval, tasks, textArea);
			if(!m.ExecuteMyopic())
			{
				JOptionPane.showMessageDialog(this, "Max backtracks exceeded - unschedulable");
			}


			//testMyopicCreation();
			test();
			revalidate();

		}
		else if(e.getActionCommand() == "ResetMenu")
		{
			/*
			textArea.setText("");
			getContentPane().remove(taskPanel);

			taskPanel = new JPanel();
			taskPanel.add(createButtons());
			taskPanel.add(createRowOfLabels());
			taskPanel.add(createRowOfTextBoxes());
			*/
			textArea.setText("");
			getContentPane().remove(graphPanel);
			getContentPane().revalidate();
			getContentPane().add(taskPanel, BorderLayout.CENTER);
			revalidate();
		}

	}
}
